package com.alibaba.citrus.ots.price.repository.impl;

import com.alibaba.citrus.ots.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.ots.common.exception.RepositoryException;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.citrus.ots.price.ability.functions.factory.price.process.PriceProcess;
import com.alibaba.citrus.ots.price.ability.functions.factory.price.process.PropertyProcessManager;
import com.alibaba.citrus.ots.price.repository.PriceQueryRepository;
import com.alibaba.cz.base.model.category.complex.CategorySDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.db.dto.UniRecord;
import com.alibaba.lattice2.epoch.db.dto.query.QueryResponse;
import com.alibaba.lattice2.epoch.db.dto.query.SqlQueryRequest;
import com.alibaba.lattice2.epoch.db.service.UniDataAccessor;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.model.dto.WmsQueryWarehouseZoneListRequest;
import com.epoch.app.bcots.model.dto.WmsQueryWarehouseZoneListResponse;
import com.epoch.app.bcots.service.UnifiedInventoryService;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.LoadSinglePriceDimensionRequest;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.LoadSinglePriceDimensionResponse;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QueryDimensionIdAndDescRequest;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QueryDimensionIdAndDescResponse;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QueryDimensionListByDimensionIdListRequest;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QueryDimensionListByDimensionIdListResponse;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QueryPriceDimensionByTableNameRequest;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QueryPriceDimensionByTableNameResponse;
import com.epoch.app.otsforecastsales.domian.pricedimension.dto.QuerySingleDimensionByDimensionIdRequest;
import com.epoch.app.otsforecastsales.domian.pricedimension.model.PriceDimension;
import com.epoch.app.otsforecastsales.domian.pricedimension.service.PriceDimensionService;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.BatchQueryByMd5CodeListRequest;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.BatchQueryByMd5CodeListResponse;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.LoadRequest;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.LoadResponse;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.QueryPriceDimensionConfigRequest;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.QueryPriceDimensionConfigResponse;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.QueryPriceRulePageListByPriceTypeIdOrDimensionIdRequest;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.QueryPriceRulePageListByPriceTypeIdOrDimensionIdResponse;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.QueryPriceTypeIdAndDimensionIdRequest;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.dto.QueryPriceTypeIdAndDimensionIdResponse;
import com.epoch.app.otsforecastsales.domian.pricepropertyconfig.service.PricePropertyConfigService;
import com.epoch.app.otsforecastsales.domian.pricerecord.dto.QueryPriceRecordListByPriceRecordIdListRequest;
import com.epoch.app.otsforecastsales.domian.pricerecord.dto.QueryPriceRecordListByPriceRecordIdListResponse;
import com.epoch.app.otsforecastsales.domian.pricerecord.model.PriceRecord;
import com.epoch.app.otsforecastsales.domian.pricerecord.service.PriceRecordService;
import com.epoch.app.otsforecastsales.domian.pricetype.dto.QueryPriceTypeByPriceTypeIdLIstRequest;
import com.epoch.app.otsforecastsales.domian.pricetype.dto.QueryPriceTypeByPriceTypeIdLIstResponse;
import com.epoch.app.otsforecastsales.domian.pricetype.dto.QueryPriceTypeIdAndDescRequest;
import com.epoch.app.otsforecastsales.domian.pricetype.dto.QueryPriceTypeIdAndDescResponse;
import com.epoch.app.otsforecastsales.domian.pricetype.model.PriceType;
import com.epoch.app.otsforecastsales.domian.pricetype.service.PriceTypeService;
import com.epoch.app.otsforecastsales.ofspricepropertyconfigindex.dto.QueryListRequest;
import com.epoch.app.otsforecastsales.ofspricepropertyconfigindex.model.OfsPricePropertyConfigIndex;
import com.epoch.app.otsforecastsales.ofspricepropertyconfigindex.service.OfsPricePropertyConfigIndexService;
import com.epoch.app.otsplatformenhance.dto.request.SaleScopeRequest;
import com.epoch.app.otsplatformenhance.model.dto.GetLoginEmployOrganizationPermissionsPriceRequest;
import com.epoch.app.otsplatformenhance.model.dto.GetOrgChannelRelationByOrgId2Request;
import com.epoch.app.otsplatformenhance.model.dto.OrganizationChannelRelationSDO;
import com.epoch.app.otsplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.otsplatformenhance.service.OtsPlatformEnhanceService;
import com.epoch.app.otspricecenter.dto.request.PageQueryPriceRequest;
import com.epoch.app.otspricecenter.enums.DimensionPropertyEnum;
import com.epoch.app.otspricecenter.model.dto.CategoryExtSDO;
import com.epoch.app.otspricecenter.model.dto.ExtraShowColumn;
import com.epoch.app.otspricecenter.model.dto.PageQueryPriceResponse;
import com.epoch.app.otspricecenter.model.dto.PriceCategorySDO;
import com.epoch.app.otspricecenter.model.dto.RegularPriceRequest;
import com.epoch.app.otspricecenter.model.dto.RegularPriceResponse;
import com.epoch.app.otspricecenter.model.enums.PriceTypeEnum;
import com.epoch.app.otspricecenter.sdo.PriceDimensionConfigSDO;
import com.epoch.app.otspricecenter.sdo.PriceDimensionSDO;
import com.epoch.app.otspricecenter.sdo.PricePropertyConfigSDO;
import com.epoch.app.otspricecenter.sdo.PriceRecordSDO;
import com.epoch.app.otspricecenter.sdo.PriceTypeSDO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author: qiaojiange
 * @create: 2021/09/15
 * @Description 价格查询 Repository
 */
@Repository
public class PriceQueryRepositoryImpl implements PriceQueryRepository {

    @Resource
    private PriceTypeService priceTypeService;

    //领域模型名称发生变化，替代原来的priceRuleService
    @Resource
    private PricePropertyConfigService pricePropertyConfigService;

    @Resource
    private PriceDimensionService priceDimensionService;


    @Resource
    private PriceRecordService priceRecordService;


    @Resource
    private UnifiedInventoryService unifiedInventoryService;

    @Resource
    private OtsPlatformEnhanceService otsPlatformEnhanceService;

    @Resource
    private PropertyProcessManager propertyProcessManager;

    private static Pattern LINE_PATTERN = Pattern.compile("_(\\w)");

    @Resource
    private PropertyProcessManager manager;

    @Resource
    UniDataAccessor uniDataAccessor;

    @Resource
    private OfsPricePropertyConfigIndexService ofsPricePropertyConfigIndexService;

    private Log log = Log.getLogger(PriceQueryRepositoryImpl.class);

    @Override
    @RepositoryInvoker(value = "测试使用", printLog = true, errorCode = "xxxxx")
    public Result<Map<String, List<PriceCategorySDO>>> getTypeAndDimensionTree() {

        //先从缓存中取值
        if (true) {
            //todo 韩国...
        }
        //获取价格类型id和维度的对应关系
        QueryPriceTypeIdAndDimensionIdResponse priceTypeIdAndDimensionIdResponse = pricePropertyConfigService.queryPriceTypeIdAndDimensionId(new QueryPriceTypeIdAndDimensionIdRequest());
        if (CollectionUtils.isEmpty(priceTypeIdAndDimensionIdResponse.getResult())) {
            return Result.success(new HashMap<>());
        }
        List<PricePropertyConfigSDO> pricePropertyConfigSDOS = JSONObject.parseArray(JSONObject.toJSONString(priceTypeIdAndDimensionIdResponse.getResult()), PricePropertyConfigSDO.class);

        //价格id和维度id的对应关系
        Map<String, Set<String>> priceIdAndDimensionId = new HashMap<>();
        pricePropertyConfigSDOS.stream().collect(Collectors.groupingBy(PricePropertyConfigSDO::getPriceTypeId)).entrySet().stream().forEach(item -> {
            priceIdAndDimensionId.put(item.getKey(), item.getValue().stream().map(o -> o.getDimensionId()).collect(Collectors.toSet()));
        });

        //获取价格类型
        QueryPriceTypeIdAndDescResponse priceTypeIdAndDescResponse = priceTypeService.queryPriceTypeIdAndDesc(new QueryPriceTypeIdAndDescRequest());
        List<PriceTypeSDO> priceTypeSDOS = JSONObject.parseArray(JSONObject.toJSONString(priceTypeIdAndDescResponse.getResult()), PriceTypeSDO.class);
        //priceTypeId和priceTypeDesc的对应关系
        Map<String, String> priceTypeMap = priceTypeSDOS.stream().
                filter(e->StringUtils.isNotBlank(e.getPriceTypeId()) && StringUtils.isNotBlank(e.getPriceTypeDesc())).
                collect(Collectors.toMap(PriceTypeSDO::getPriceTypeId,  PriceTypeSDO::getPriceTypeDesc));

        //获取维度类型
        QueryDimensionIdAndDescResponse dimensionIdAndDescResponse = priceDimensionService.queryDimensionIdAndDesc(new QueryDimensionIdAndDescRequest());
        List<PriceDimensionSDO> dimensionSDOS = JSONObject.parseArray(JSONObject.toJSONString(dimensionIdAndDescResponse.getResult()), PriceDimensionSDO.class);
        //dimensionId和dimensionDesc的对应关系
        Map<String, String> dimensionDescMap = dimensionSDOS.stream().
                filter(e->StringUtils.isNotBlank(e.getDimensionId()) && StringUtils.isNotBlank(e.getDimensionDesc())).
                collect(Collectors.toMap(PriceDimensionSDO::getDimensionId, PriceDimensionSDO::getDimensionDesc));
        //dimensionId和dimensionRule的对应关系
        Map<String, String> dimensionRuleMap = dimensionSDOS.stream().
                filter(e->StringUtils.isNotBlank(e.getDimensionId()) && StringUtils.isNotBlank(e.getDimensionRule())).
                collect(Collectors.toMap(PriceDimensionSDO::getDimensionId, PriceDimensionSDO::getDimensionRule));
        //拼装类目数据
        List<PriceCategorySDO> list = Lists.newArrayList();
        priceIdAndDimensionId.entrySet().stream().forEach(item -> {
            //拼装一级类目
            PriceCategorySDO priceCategorySDO = new PriceCategorySDO();

            CategorySDO categorySDO = new CategorySDO();
            categorySDO.setVirtual(false);
            categorySDO.setLeaf(false);
            categorySDO.setCategoryId("TRUNK-" + item.getKey() + "");
            categorySDO.setCategoryName(priceTypeMap.get(item.getKey()));
            categorySDO.setSortOrder(0);
            categorySDO.setRoot(true);
            categorySDO.setForbid(false);
            categorySDO.setParentCategoryId("0");
            categorySDO.setRootCategoryId("TRUNK-" + item.getKey() + "");
            categorySDO.setStatus(1);
            priceCategorySDO.setCategorySDO(categorySDO);
            priceCategorySDO.setForbid(false);
            priceCategorySDO.setSelected(true);

            List<CategoryExtSDO> children = Lists.newArrayList();
            //拼装二级类目
            item.getValue().stream().forEach(dimension -> {

                CategoryExtSDO categoryExtSDO = new CategoryExtSDO();
                com.alibaba.cz.base.model.category.complex.CategorySDO secondCategorySDO = new com.alibaba.cz.base.model.category.complex.CategorySDO();

                secondCategorySDO.setVirtual(false);
                secondCategorySDO.setLeaf(true);
                secondCategorySDO.setCategoryId("LEAF-" + dimension + "-" + item.getKey());
                secondCategorySDO.setCategoryName(dimensionDescMap.get(dimension));
                secondCategorySDO.setSortOrder(0);
                secondCategorySDO.setRoot(false);
                secondCategorySDO.setForbid(false);
                secondCategorySDO.setParentCategoryId("TRUNK-" + item.getKey() + "");
                secondCategorySDO.setRootCategoryId("TRUNK-" + item.getKey() + "");
                secondCategorySDO.setStatus(1);
                //动态列的获取以及配置
                secondCategorySDO.setFeatures(detailColumn(dimensionDescMap.get(dimension), dimensionRuleMap.get(dimension)));
                categoryExtSDO.setCategorySDO(secondCategorySDO);
                categoryExtSDO.setForbid(false);
                categoryExtSDO.setSelected(true);
                children.add(categoryExtSDO);
            });
            priceCategorySDO.setChildren(children);
            list.add(priceCategorySDO);

        });
        Map<String, List<PriceCategorySDO>> children = new HashMap<>();
        children.put("children", list);
        return Result.success(children);
    }

    @Override
    @RepositoryInvoker("价格列表查询资源层")
    public Result<List<PageQueryPriceResponse>> queryPricePageList(PageQueryPriceRequest pageQueryPriceRequest) {
        String priceTypeId = null;
        String dimensionId = null;

        if (StringUtils.isBlank(pageQueryPriceRequest.getPriceTypeOrDimensionId())) {
            return Result.success(Lists.newArrayList());
        }

        String priceTypeOrDimensionId = pageQueryPriceRequest.getPriceTypeOrDimensionId();
        if (StringUtils.isNotBlank(priceTypeOrDimensionId)) {
            String structure = priceTypeOrDimensionId.split("-")[0];
            if ("TRUNK".equals(structure)) {
                //一级节点表示传过来的是价格类型id
                priceTypeId = priceTypeOrDimensionId.split("-")[1];
            } else {
                //二级节点表示传过来的维度id
                dimensionId = priceTypeOrDimensionId.split("-")[1];
                //拼上父节点的价格id
                priceTypeId = priceTypeOrDimensionId.split("-")[2];
            }
        }

        //查询price_rule 价格维度数据表
        //组装查询条件
        QueryPriceRulePageListByPriceTypeIdOrDimensionIdRequest dimensionIdRequest = new QueryPriceRulePageListByPriceTypeIdOrDimensionIdRequest();
        dimensionIdRequest.setDimensionId(dimensionId);
        dimensionIdRequest.setPriceTypeId(priceTypeId);
        dimensionIdRequest.setLimit(pageQueryPriceRequest.getLimit());
        dimensionIdRequest.setStart(pageQueryPriceRequest.getStart());
        dimensionIdRequest.setStartDate(DateUtils.obtainCurrentDayBeginOrEnd(pageQueryPriceRequest.getStartDate(),true));
        dimensionIdRequest.setEndDate(DateUtils.obtainCurrentDayBeginOrEnd(pageQueryPriceRequest.getEndDate(),false));

        //加权限控制
        Result<List<com.epoch.app.otsplatformenhance.sdo.OrganizationSDO>> loginEmployeeSaleOrganization = otsPlatformEnhanceService.getLoginEmployeeSaleOrganization();
        if (Objects.nonNull(loginEmployeeSaleOrganization) && CollectionUtils.isNotEmpty(loginEmployeeSaleOrganization.getResult())) {
            com.epoch.app.otsplatformenhance.sdo.OrganizationSDO organizationSDO = loginEmployeeSaleOrganization.getResult().get(0);
            if (Objects.nonNull(organizationSDO) && StringUtils.isNotBlank(organizationSDO.getId())) {
                String organizationId = organizationSDO.getId();
                Map<String, String> salesOrganizationMap = propertyProcessManager.getPropertyProcess(DimensionPropertyEnum.ORG_SALES_ORGANIZATION_CODE.getKey())
                        .obtainInnerCodeAndOuterCodeMap(Lists.newArrayList(organizationId), true);
                String organizationOutCode = salesOrganizationMap.get(organizationId);
                if (StringUtils.isNotBlank(organizationOutCode)) {
                    //权限先放开
                    //dimensionIdRequest.setSalesOrganization(DimensionPropertyEnum.ORG_SALES_ORGANIZATION_CODE.getKey() + "_" + organizationOutCode);
                }
            }

        }

        dimensionIdRequest.setItemId(pageQueryPriceRequest.getItemId());

        QueryPriceRulePageListByPriceTypeIdOrDimensionIdResponse priceRuleResponse = pricePropertyConfigService.queryPriceRulePageListByPriceTypeIdOrDimensionId(dimensionIdRequest);

        if (CollectionUtils.isEmpty(priceRuleResponse.getResult())) {
            return Result.success(new ArrayList<>());
        }

        //价格属性数据配置List<data>
        List<PricePropertyConfigSDO> pricePropertyConfigSDOS = JSONObject.parseArray(JSONObject.toJSONString(priceRuleResponse.getResult()), PricePropertyConfigSDO.class);


        //获取价格类型idList
        List<String> priceTypeIdList = pricePropertyConfigSDOS.stream().filter(item -> StringUtils.isNotBlank(item.getPriceTypeId())).map(item -> item.getPriceTypeId()).collect(Collectors.toSet()).stream().collect(Collectors.toList());


        //获取价格类型id和desc的map
        QueryPriceTypeByPriceTypeIdLIstRequest queryPriceTypeByPriceTypeIdLIstRequest = new QueryPriceTypeByPriceTypeIdLIstRequest();
        queryPriceTypeByPriceTypeIdLIstRequest.setPriceTypeIdList(priceTypeIdList);
        QueryPriceTypeByPriceTypeIdLIstResponse priceTypeResponse = priceTypeService.queryPriceTypeByPriceTypeIdLIst(queryPriceTypeByPriceTypeIdLIstRequest);
        Map<String, String> priceTypeMap = Maps.newHashMap();

        if (CollectionUtils.isNotEmpty(priceTypeResponse.getResult())) {
            priceTypeMap = JSONObject.parseArray(JSONObject.toJSONString(priceTypeResponse.getResult()), PriceTypeSDO.class).stream().collect(Collectors.toMap(PriceTypeSDO::getPriceTypeId, PriceTypeSDO::getPriceTypeDesc));
        }

        //获取价格记录idList
        List<String> priceRecordIdList = pricePropertyConfigSDOS.stream().filter(item -> StringUtils.isNotBlank(item.getPriceRecordId())).map(item -> item.getPriceRecordId()).collect(Collectors.toSet()).stream().collect(Collectors.toList());
        //获取价格记录priceRecordId:priceRecordSDO的数据map
        QueryPriceRecordListByPriceRecordIdListRequest queryPriceRecordListByPriceRecordIdListRequest = new QueryPriceRecordListByPriceRecordIdListRequest();
        queryPriceRecordListByPriceRecordIdListRequest.setPriceRecordIdList(priceRecordIdList);
        QueryPriceRecordListByPriceRecordIdListResponse priceRecordResponse = priceRecordService.queryPriceRecordListByPriceRecordIdList(queryPriceRecordListByPriceRecordIdListRequest);

//        按照 recordId 对价格记录进行分类
        Map<String, List<PriceRecordSDO>> priceRecordMap = JSONObject.parseArray(JSONObject.toJSONString(priceRecordResponse.getResult()), PriceRecordSDO.class).stream().collect(Collectors.groupingBy(PriceRecordSDO::getPriceRecordId));

        Map<String, String> priceUniteMap = Maps.newHashMap();
        if (MapUtils.isNotEmpty(priceRecordMap)) {
            List<String> priceUnite = Lists.newArrayList();
            priceRecordMap.keySet().stream().forEach(item -> {
                List<String> priceUniteList = priceRecordMap.get(item).stream().map(sdo -> sdo.getPriceUnite()).collect(Collectors.toList());
                priceUnite.addAll(priceUniteList);
            });
            priceUniteMap = manager.getPropertyProcess(DimensionPropertyEnum.SALES_UNIT_CODE.getKey()).obtainCodeAndDescMap(priceUnite, false);
        }

        //组装数据
        List<PageQueryPriceResponse> responses = Lists.newArrayList();

        //获取维度属性名和值的listMap
        List<String> dimensionPropertyGroup = pricePropertyConfigSDOS.stream().map(x -> x.getDimensionPropertiesGroup()).collect(Collectors.toList());
        //获取维度规则属性和值list的对应关系
        Map<String, List<String>> dimensionPropertyCodeAndValueMap = obtainDimensionPropertyAndDataMap(dimensionPropertyGroup);
        //获取属性名称1:(编码:描述)N的对应关系
        Map<String, Map<String, String>> dimensionPropertyMap = obtainDimensionPropertyMap(dimensionPropertyCodeAndValueMap);


        for (PricePropertyConfigSDO pricePropertyConfigSDO : pricePropertyConfigSDOS) {
            PageQueryPriceResponse pageQueryPriceResponse = new PageQueryPriceResponse();
            pageQueryPriceResponse.setPriceTypeDesc(priceTypeMap.get(pricePropertyConfigSDO.getPriceTypeId()));
            List<PriceRecordSDO> priceRecordSDOS = priceRecordMap.get(pricePropertyConfigSDO.getPriceRecordId());
            if (CollectionUtils.isNotEmpty(priceRecordSDOS)) {
                Long moneyAmount = priceRecordSDOS.get(0).getMoneyAmount();
                if(Objects.nonNull(moneyAmount)){
                    BigDecimal bigDecimal = new BigDecimal(moneyAmount);
                    pageQueryPriceResponse.setAmount(bigDecimal.divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_DOWN).toString());
                }
                pageQueryPriceResponse.setCurrency(priceRecordSDOS.get(0).getCurrency());
                pageQueryPriceResponse.setPriceNumber(priceRecordSDOS.get(0).getItemCount());
                pageQueryPriceResponse.setPriceUnite(priceUniteMap.get(priceRecordSDOS.get(0).getPriceUnite()));
            }

            if (Objects.nonNull(pricePropertyConfigSDO.getPriceStartDate())) {
                pageQueryPriceResponse.setEffectiveStartDate(new SimpleDateFormat("yyyy/MM/dd").format(pricePropertyConfigSDO.getPriceStartDate()));
            }
            if (Objects.nonNull(pricePropertyConfigSDO.getPriceEndDate())) {
                pageQueryPriceResponse.setEffectiveEndDate(new SimpleDateFormat("yyyy/MM/dd").format(pricePropertyConfigSDO.getPriceEndDate()));
            }

            //动态列配置
            Map<String, String> columnDataGroup = Maps.newHashMap();
            String dimensionPropertiesGroup = pricePropertyConfigSDO.getDimensionPropertiesGroup();
            if (StringUtils.isNotBlank(dimensionPropertiesGroup)) {
                Map<String, String> map = detailColumnDate(columnDataGroup, dimensionPropertiesGroup);
                Map<String, String> features = Maps.newHashMap();
                //编码转描述
                for (String propertyCode : map.keySet()) {
                    Map<String, String> codeAndDescMap = dimensionPropertyMap.get(propertyCode);
                    String propertyValue = map.get(propertyCode);

                    if (MapUtils.isEmpty(codeAndDescMap)) {
                        //未查询到了内外码关系
                        features.put(this.toHump(propertyCode), map.get(propertyCode));
                    } else {
                        //查询到了内外码关系
                        features.put(this.toHump(propertyCode), codeAndDescMap.get(propertyValue));
                    }


                    //单独,查询存储位置---注意：这里是一个特殊逻辑
                    if (DimensionPropertyEnum.STORE_PLACE.getKey().equals(propertyCode)) {
                        String storeName = obtainStoreName(map, propertyValue);
                        features.put(this.toHump(propertyCode), storeName);
                    }
                }
                pageQueryPriceResponse.setFeatures(features);
            }


            responses.add(pageQueryPriceResponse);
        }

        log.info("价格列表查询结果 = {}",responses);
        //返回结果
        return Result.listSuccess(responses, priceRuleResponse.getTotal());
    }


    @Override
    @RepositoryInvoker("价格列表查询ES资源层")
    public Result<List<PageQueryPriceResponse>> queryPricePageListFromES(PageQueryPriceRequest pageQueryPriceRequest) {

        //校验入参
        if (StringUtils.isBlank(pageQueryPriceRequest.getPriceTypeOrDimensionId())) {
            return Result.success(Lists.newArrayList());
        }
        //构建入参
        SqlQueryRequest sqlQueryRequest = new SqlQueryRequest();
        sqlQueryRequest.setAppCode("ots_forecast_sales");
        sqlQueryRequest.setTableCode("ofs_price_property_config_index");

        //查询记录总数
        long count = 0;
        String queryCountSql = obtainSql(pageQueryPriceRequest, true, false);
        if(Objects.isNull(queryCountSql)){
            return Result.success(Lists.newArrayList());
        }
        sqlQueryRequest.setSql(queryCountSql);
        log.info("当前查询价格数据count的sql = {}",queryCountSql);
        QueryResponse queryCountResponse = uniDataAccessor.sqlQuery(sqlQueryRequest);
        log.info("当前查询价格数据count的结果 = {}", JSONObject.toJSONString(queryCountResponse));

        long queryTotalSql = (long) queryCountResponse.getResult().get(0).getValues().get("total");
        if (Objects.isNull(queryCountResponse) || queryTotalSql == count) {
            return Result.success(new ArrayList<>());
        }

        Result<List<PageQueryPriceResponse>> result = Result.success(new ArrayList<>());
        result.setTotal(Integer.parseInt(new Long(queryTotalSql).toString()));

        //查询数据
        String queryDataListSql = obtainSql(pageQueryPriceRequest, false, true);
        if(Objects.isNull(queryDataListSql)){
            return Result.success(Lists.newArrayList());
        }
        sqlQueryRequest.setSql(queryDataListSql);
        log.info("当前查询价格列表数据的sql = {}",queryDataListSql);
        QueryResponse queryResultResponse = uniDataAccessor.sqlQuery(sqlQueryRequest);
        log.info("当前查询价格数据列表的结果 = {}", JSONObject.toJSONString(queryResultResponse));
        //判空
        if (Objects.isNull(queryResultResponse) || CollectionUtils.isEmpty(queryResultResponse.getResult())) {
            return Result.success(new ArrayList<>());
        }

        List<PageQueryPriceResponse> pageQueryPriceResponses = new ArrayList<>();
        //结果处理
        obtainPriceDataFromEs(pageQueryPriceResponses, queryResultResponse, pageQueryPriceRequest);
        result.setResult(pageQueryPriceResponses);
        return result;

    }

    //对结果进行解析
    @RepositoryInvoker("解析自定义SQL查询结果")
    private void obtainPriceDataFromEs(List<PageQueryPriceResponse> pageQueryPriceResponses,
                                       QueryResponse queryResultResponse, PageQueryPriceRequest pageQueryPriceRequest) {

        List<UniRecord> uniRecords = queryResultResponse.getResult();
        uniRecords.stream().map(UniRecord::getValues).forEach(e -> {
            PageQueryPriceResponse pageQueryPriceResponse = new PageQueryPriceResponse();
            pageQueryPriceResponse.setEffectiveStartDate(DateUtils.toDateStr(Long.parseLong((String) e.get("configPriceStartDate")), "yyyy/MM/dd"));
            pageQueryPriceResponse.setEffectiveEndDate(DateUtils.toDateStr(Long.parseLong((String) e.get("configPriceEndDate")), "yyyy/MM/dd"));
            pageQueryPriceResponse.setPriceTypeDesc(e.get("typePriceTypeDesc") == null ? null : (String) e.get("typePriceTypeDesc"));
            Integer recordMoneyAmount = Integer.parseInt(e.get("recordMoneyAmount") == null ? null : (String) e.get("recordMoneyAmount"));
            if (Objects.nonNull(recordMoneyAmount)) {
                pageQueryPriceResponse.setAmount(
                        new BigDecimal(recordMoneyAmount).divide(new BigDecimal(100)).
                                setScale(2, RoundingMode.HALF_DOWN).toString());
            }
            pageQueryPriceResponse.setPriceUnite(e.get("recordPriceUniteDesc") == null ? null : (String) e.get("recordPriceUniteDesc"));
            pageQueryPriceResponse.setPriceNumber(e.get("recordItemCount") == null ? null : Long.parseLong(e.get("recordItemCount").toString()));
            pageQueryPriceResponse.setCurrency(e.get("recordCurrency") == null ? null : (String) e.get("recordCurrency"));
            pageQueryPriceResponse.setItemCode(e.get("configMaterialCodeFlag") == null ? null : (String) e.get("configMaterialCodeFlag"));
            Map<String, String> features = Maps.newHashMap();
            //获取选择的维度id
            String dimensionId = obtainDimensionSelected(pageQueryPriceRequest,true,false);
            List<String> propertyList = obtainDimensionPropertyList(dimensionId);
            propertyList.stream().forEach(property -> {
                //转驼峰并首字符大写
                char[] chars = toHump(property).toCharArray();
                if (97 <= chars[0] && chars[0] <= 122) {
                    chars[0] ^= 32;
                }
                features.put(toHump(property), (String) e.get("config" + String.valueOf(chars)));
            });
            pageQueryPriceResponse.setFeatures(features);
            pageQueryPriceResponses.add(pageQueryPriceResponse);

        });
    }


    /**
     * 获取选择的层级
     *
     * @param pageQueryPriceRequest
     * @return
     */
    private String obtainDimensionSelected(PageQueryPriceRequest pageQueryPriceRequest, Boolean dimension, Boolean priceType) {
        //获取层级
        String resultStr = null;
        String priceTypeOrDimensionId = pageQueryPriceRequest.getPriceTypeOrDimensionId();
        if (StringUtils.isNotBlank(priceTypeOrDimensionId)) {
            String structure = priceTypeOrDimensionId.split("-")[0];
            if (!"TRUNK".equals(structure)) {
                //一级节点表示传过来的是价格类型id
                //二级节点表示传过来的维度id
                if (dimension) {
                    resultStr = priceTypeOrDimensionId.split("-")[1];
                }
                if (priceType) {
                    resultStr = priceTypeOrDimensionId.split("-")[2];
                }
            }
        }
        if (StringUtils.isBlank(resultStr)) {
            throw new RepositoryException("OTS-07-005-01-15-012");
        }
        return resultStr;

    }

    private String obtainSql(PageQueryPriceRequest pageQueryPriceRequest, Boolean queryCount, Boolean queryResult) {
        //获取维度类型
        String dimensionId = obtainDimensionSelected(pageQueryPriceRequest, true, false);

        //获取价格类型
        String priceTypeId = obtainDimensionSelected(pageQueryPriceRequest, false, true);


        StringBuilder sql = null;
        //查询记录总数
        if (queryCount) {
            sql = new StringBuilder("select count(config_id) total from ofs_price_property_config_index where 1 = 1");
        }
        if (queryResult) {
            String tableColumn = "dimension_dimension_rule,config_sales_unit_code,config_channel_code_flag,type_price_type_id," +
                    "config_updater,config_price_end_date,record_price_record_id,config_status,config_customer_sale_address_code" +
                    "dimension_dimension_id,record_id,config_org_sales_organization_code,config_material_code," +
                    "record_version,type_price_type_desc,config_price_type_id,config_dimension_properties_group," +
                    "record_money_percentage,config_price_start_date,config_id,config_gmt_modify,record_gmt_modify," +
                    "config_sales_area,config_customer_group,config_factory_code,config_price_list_code,config_sales_department_code,"+
                    "config_sales_group_code,config_customer_code,config_department_code,config_price_area,"+
                    "record_updater,record_item_count,record_price_unite,config_item_id,config_price_record_id,config_creator," +
                    "config_gmt_create,record_money_amount,dimension_dimension_desc,config_version,record_currency," +
                    "config_customer_send_address_code,config_features,config_channel_code,config_sc_item_group_code," +
                    "config_org_sales_organization_code_flag,config_tenant_id,record_gmt_create,config_dimension_id," +
                    "record_creator,config_md5_code,record_price_unite_desc,record_features,record_status";
            sql = new StringBuilder("select * from ofs_price_property_config_index where 1 = 1");
        }

        sql.append(" and record_status = 1 and type_status = 1 and dimension_status = 1 ");

        sql.append(" and config_dimension_id =" + dimensionId);

        //获取维度属性列表
        List<String> dimensionPropertyList = obtainDimensionPropertyList(dimensionId);
        for (String ruleProperty : dimensionPropertyList) {
            sql.append(" and config_" + ruleProperty + "  is not null  ");
        }

        //价格不能为空
        sql.append(" and record_money_amount is not null ");

        //定价数量不能为空
        sql.append(" and record_item_count is not null ");


        if (StringUtils.isNotBlank(pageQueryPriceRequest.getItemId())) {
            sql.append(" and config_item_id = " + pageQueryPriceRequest.getItemId());
        }

        if(Objects.nonNull(pageQueryPriceRequest.getStartDate())){
            sql.append(" and config_price_start_date >="+pageQueryPriceRequest.getStartDate().getTime());
        }
        if(Objects.nonNull(pageQueryPriceRequest.getEndDate())){
            sql.append(" and config_price_end_date <="+pageQueryPriceRequest.getEndDate().getTime());
        }

        //加权限控制
        List<String> organizationIds = Lists.newArrayList();
        //获取销售组织外部编码
        List<String> organizationOutCodes = Lists.newArrayList();
        GetLoginEmployOrganizationPermissionsPriceRequest permissionsPriceRequest = new GetLoginEmployOrganizationPermissionsPriceRequest();
        permissionsPriceRequest.setType(104);
        Result<List<OrganizationSDO>> loginEmployeeSaleOrganization = otsPlatformEnhanceService.getLoginEmployOrganizationPermissionsPrice(permissionsPriceRequest);
        log.info("当前登录用户的销售组织信息 = {}", JSONObject.toJSONString(loginEmployeeSaleOrganization));
        if (Objects.nonNull(loginEmployeeSaleOrganization) && CollectionUtils.isNotEmpty(loginEmployeeSaleOrganization.getResult())) {
            List<com.epoch.app.otsplatformenhance.sdo.OrganizationSDO> organizationSDOList = loginEmployeeSaleOrganization.getResult();
            if (CollectionUtils.isNotEmpty(organizationSDOList)) {
                organizationIds = organizationSDOList.stream().filter(e -> StringUtils.isNotBlank(e.getId())).distinct().map(e -> e.getId()).collect(Collectors.toList());
                Map<String, String> salesOrganizationMap = propertyProcessManager.getPropertyProcess(DimensionPropertyEnum.ORG_SALES_ORGANIZATION_CODE.getKey())
                        .obtainInnerCodeAndOuterCodeMap(organizationIds, true);
                organizationIds.forEach(e -> organizationOutCodes.add(salesOrganizationMap.get(e)));
            }
        }

        if (CollectionUtils.isEmpty(organizationOutCodes)) {
            log.error("未查询到当前登录用户的销售组织信息");
            return null;
        }

        //获取业务渠道外部编码
        List<String> channelOutCodes = Lists.newArrayList();
        GetOrgChannelRelationByOrgId2Request channelRelationByOrgId2Request = new GetOrgChannelRelationByOrgId2Request();
        channelRelationByOrgId2Request.setIds(organizationIds);
        channelRelationByOrgId2Request.setStatus(1);
        Result<List<OrganizationChannelRelationSDO>> orgChannelRelationResult = otsPlatformEnhanceService.getOrgChannelRelationByOrgId2(channelRelationByOrgId2Request);
        log.info("当前登录用户的业务渠道信息 = {}", JSONObject.toJSONString(orgChannelRelationResult));
        if (Objects.nonNull(orgChannelRelationResult) && CollectionUtils.isNotEmpty(orgChannelRelationResult.getResult())) {
            List<OrganizationChannelRelationSDO> orgChannelRelations = orgChannelRelationResult.getResult();
            channelOutCodes = orgChannelRelations.stream().filter(e -> StringUtils.isNotBlank(e.getOutCode()))
                    .map(OrganizationChannelRelationSDO::getOutCode).distinct().collect(Collectors.toList());
        }

        if (PriceTypeEnum.ZP01.getCode().equals(priceTypeId)) {
            log.info("当前登录用户的业务渠道信息 = {}", JSONObject.toJSONString(orgChannelRelationResult));
            //常规价需要对业务渠道做权限控制
            if (CollectionUtils.isEmpty(channelOutCodes)) {
                log.error("未查询到当前用户的渠道信息");
                return null;
            }
        }


        if (CollectionUtils.isNotEmpty(organizationOutCodes)) {
            sql.append(" and config_org_sales_organization_code_flag.keyword in (");
            int size = organizationOutCodes.size();
            for (int i = 0; i < size; i++) {
                if (i == size - 1) {
                    sql.append("'" + organizationOutCodes.get(i) + "')");
                } else {
                    sql.append("'" + organizationOutCodes.get(i) + "'" + ",");
                }
            }
        }

        if (PriceTypeEnum.ZP01.getCode().equals(priceTypeId)) {
            sql.append(" and config_channel_code_flag.keyword in (");
            int size = channelOutCodes.size();
            for (int i = 0; i < size; i++) {
                if (i == size - 1) {
                    sql.append("'" + channelOutCodes.get(i) + "')");
                } else {

                    sql.append("'" + channelOutCodes.get(i) + "'" + ",");
                }
            }
        }

        //分页
        if(Objects.isNull(pageQueryPriceRequest.getStart())){
            pageQueryPriceRequest.setStart(0);
        }
        //分页
        if(Objects.isNull(pageQueryPriceRequest.getLimit())){
            pageQueryPriceRequest.setLimit(20);
        }
        sql.append(" limit " +pageQueryPriceRequest.getStart() +","+pageQueryPriceRequest.getLimit());

        return sql.toString();
    }

    /**
     * 获取维度属性数组
     * @param dimensionId
     * @return
     */
    private List<String> obtainDimensionPropertyList(String dimensionId){
        //根据维度id获取维度规则
        QuerySingleDimensionByDimensionIdRequest dimensionRequest = new QuerySingleDimensionByDimensionIdRequest();
        dimensionRequest.setDimensionId(dimensionId);
        PriceDimension priceDimension = priceDimensionService.querySingleDimensionByDimensionId(dimensionRequest);
        if (Objects.isNull(priceDimension)) {
            log.error("价格维度查询失败，请检查维度配置表是否存在该维度：" + dimensionId);
            throw new RepositoryException("OTS-07-005-01-15-011");
        }
        List<String> property = Lists.newArrayList();
        for (String ruleProperty : priceDimension.getDimensionRule().split(",")) {
            String[] dimensionRuleArr = ruleProperty.split("\\+");
            property.add(dimensionRuleArr[1]);
        }
        return property;
    }


    /**
     * 获取存储位置名称
     * @param map 存储的维度数据值映射表
     * @param propertyValue 属性值
     * @return
     */
    private String obtainStoreName(Map<String, String> map, String propertyValue) {
        WmsQueryWarehouseZoneListRequest request = new WmsQueryWarehouseZoneListRequest();
        //获取工厂编码
        request.setSapFactoryCode(map.get(DimensionPropertyEnum.FACTORY_CODE.getKey()));
        request.setWarehouseCode(map.get(propertyValue));
        //查询存储位置
        WmsQueryWarehouseZoneListResponse zoneListResponse = unifiedInventoryService.wmsQueryWarehouseZoneList(request);
        String storeName = "";
        if (Objects.nonNull(zoneListResponse) && CollectionUtils.isNotEmpty(zoneListResponse.getResult())) {
            storeName = zoneListResponse.getResult().get(0).getName();
        }
        return storeName;
    }

    @Override
    public Result<PriceTypeSDO> queryPriceType(String priceTypeId) {
        QueryPriceTypeByPriceTypeIdLIstRequest priceTypeByPriceTypeIdLIstRequest = new QueryPriceTypeByPriceTypeIdLIstRequest();
        priceTypeByPriceTypeIdLIstRequest.setPriceTypeIdList(Collections.singletonList(priceTypeId));
        QueryPriceTypeByPriceTypeIdLIstResponse priceTypeResponse = priceTypeService.queryPriceTypeByPriceTypeIdLIst(priceTypeByPriceTypeIdLIstRequest);
        List<PriceType> priceTypes = JSONObject.parseArray(JSONObject.toJSONString(priceTypeResponse.getResult()), PriceType.class);

        if (CollectionUtils.isEmpty(priceTypes)) {
            return Result.success(null);
        }
        PriceType priceType = priceTypes.get(0);
        PriceTypeSDO priceTypeSDO = new PriceTypeSDO();
        BeanUtils.copyProperties(priceType, priceTypeSDO);
        priceTypeSDO.setDimensionOrder(priceType.getDemensionOrder());
        priceTypeSDO.setNegativeNumberFlag(priceType.getIsNegativeNumber() == 1 ? true : false);
        priceTypeSDO.setManualFlag(priceType.getIsManual() == 1 ? true : false);

        return Result.success(priceTypeSDO);
    }

    @Override
    public Result<PriceRecordSDO> queryPriceRecord(String recordId) {
        QueryPriceRecordListByPriceRecordIdListRequest priceRecordListByPriceRecordIdListRequest = new QueryPriceRecordListByPriceRecordIdListRequest();
        priceRecordListByPriceRecordIdListRequest.setPriceRecordIdList(Collections.singletonList(recordId));
        QueryPriceRecordListByPriceRecordIdListResponse priceRecordResponse = priceRecordService.queryPriceRecordListByPriceRecordIdList(priceRecordListByPriceRecordIdListRequest);
        List<PriceRecord> priceRecords = JSONObject.parseArray(JSONObject.toJSONString(priceRecordResponse.getResult()), PriceRecord.class);

        if (CollectionUtils.isEmpty(priceRecords)) {
            return Result.success(null);
        }

        PriceRecord priceRecord = priceRecords.get(0);

        PriceRecordSDO priceRecordSDO = new PriceRecordSDO();
        BeanUtils.copyProperties(priceRecord, priceRecordSDO);
        //设置金额百分比
        priceRecordSDO.setMoneyPercentage(priceRecord.getMoneyPercentage() == null ? null : priceRecord.getMoneyPercentage().toString());

        priceRecordSDO.setItemCount(priceRecord.getItemCount() == null ? null : priceRecord.getItemCount() + 0L);

        return Result.success(priceRecordSDO);
    }

    @Override
    public Result<List<PriceDimensionSDO>> batchQueryDimensionRule(List<String> dimensionIds) {
        QueryDimensionListByDimensionIdListRequest dimensionIdListRequest = new QueryDimensionListByDimensionIdListRequest();
        dimensionIdListRequest.setDimensionIdList(dimensionIds);
        QueryDimensionListByDimensionIdListResponse dimensionIdListResponse = priceDimensionService.queryDimensionListByDimensionIdList(dimensionIdListRequest);
        List<PriceDimensionSDO> dimensionRuleSDOS = JSONObject.parseArray(JSONObject.toJSONString(dimensionIdListResponse.getResult()), PriceDimensionSDO.class);
        return Result.success(dimensionRuleSDOS);
    }

    @Override
    public Result<List<PriceDimensionConfigSDO>> batchQueryDimensionConfig(List<String> md5List, Date useDate) {
        BatchQueryByMd5CodeListRequest queryByMd5CodeListRequest = new BatchQueryByMd5CodeListRequest();
        queryByMd5CodeListRequest.setMd5CodeList(md5List);
        //TODO qjg 这个地方要添加查询页面大小限制
        queryByMd5CodeListRequest.setLimit(10000);
        queryByMd5CodeListRequest.setUseDate(useDate);

        BatchQueryByMd5CodeListResponse response = pricePropertyConfigService.batchQueryByMd5CodeList(queryByMd5CodeListRequest);
        if (Objects.isNull(response)) {
            return Result.fail(null, "从纪元中获取维度配置数据为空!");
        }
        List<PriceDimensionConfigSDO> dimensionConfigSDOS = JSONObject.parseArray(
                JSONObject.toJSONString(response.getResult()), PriceDimensionConfigSDO.class);
        return Result.success(dimensionConfigSDOS);
    }

    @Override
    public Result<PriceDimensionSDO> queryPriceDimension(String dimensionId) {
        QueryDimensionListByDimensionIdListRequest dimensionListByDimensionIdListRequest = new QueryDimensionListByDimensionIdListRequest();
        dimensionListByDimensionIdListRequest.setDimensionIdList(Collections.singletonList(dimensionId));
        QueryDimensionListByDimensionIdListResponse dimensionResponse = priceDimensionService.queryDimensionListByDimensionIdList(dimensionListByDimensionIdListRequest);

        List<PriceDimension> dimensions = JSONObject.parseArray(JSONObject.toJSONString(dimensionResponse.getResult()), PriceDimension.class);

        if (CollectionUtils.isEmpty(dimensions)) {
            return Result.success(null);
        }

        PriceDimension dimension = dimensions.get(0);
        PriceDimensionSDO priceDimensionSDO = new PriceDimensionSDO();
        BeanUtils.copyProperties(dimension, priceDimensionSDO);

        return Result.success(priceDimensionSDO);
    }

    @Override
    public Result<PriceDimensionSDO> queryPriceDimensionByTableName(String tableName) {
        QueryPriceDimensionByTableNameRequest request = new QueryPriceDimensionByTableNameRequest();
        request.setTableName(tableName);
        QueryPriceDimensionByTableNameResponse response = priceDimensionService.queryPriceDimensionByTableName(request);

        PriceDimensionSDO priceDimensionSDO = new PriceDimensionSDO();
        BeanUtils.copyProperties(response.getResult(), priceDimensionSDO);

        return Result.success(priceDimensionSDO);
    }

    //获取所有的客户编码list
    public List<String> obtainCustomerCodeList(List<String> dimensionGroupList) {
        List<String> customerCodeList = Lists.newArrayList();
        dimensionGroupList.forEach(item -> {
            List<String> propertiesList = Lists.newArrayList(item.split(",")).stream().filter(property -> property.contains("custumer_code")).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(propertiesList)) {
                String custumerCodeStr = propertiesList.get(0);
                int index = custumerCodeStr.lastIndexOf("_");
                customerCodeList.add(custumerCodeStr.substring(index + 1));

            }
        });
        return customerCodeList;
    }


    @Override
    public Result<List<PriceDimensionSDO>> batchPriceDimension(List<String> tableNames) {
        LoadSinglePriceDimensionRequest loadSinglePriceDimensionRequest = new LoadSinglePriceDimensionRequest();
        loadSinglePriceDimensionRequest.setTableNames(tableNames);
        LoadSinglePriceDimensionResponse loadSinglePriceDimensionResponse = priceDimensionService.loadSinglePriceDimension(loadSinglePriceDimensionRequest);
        if (CollectionUtils.isNotEmpty(loadSinglePriceDimensionResponse.getResult())) {

            List<PriceDimensionSDO> priceDimensionSDOS = JSONObject.parseArray(JSONObject.toJSONString(loadSinglePriceDimensionResponse.getResult()), PriceDimensionSDO.class);
            return Result.success(priceDimensionSDOS);
        }
//        log.info("获取价格维度数据 result = {}",JSONObject.toJSONString(loadSinglePriceDimensionResponse));

        return Result.success(null);
    }

    /**
     * 查询价格维度配置
     *
     * @param sdo 根据 md5, 属性组编码、维度 ID， 价格类型进行唯一确认
     * @return
     */
    @Override
    @RepositoryInvoker(errorCode = "OTS-07-005-01-15-010",printLog = true)
    public PriceDimensionConfigSDO queryPriceDimensionConfig(PriceDimensionConfigSDO sdo) {
        QueryPriceDimensionConfigRequest request = new QueryPriceDimensionConfigRequest();
        request.setMd5Code(sdo.getMd5Code());
        request.setDimensionId(sdo.getDimensionId());
        request.setPriceTypeId(sdo.getPriceTypeId());
        request.setDimensionPropertiesGroup(sdo.getDimensionPropertiesGroup());
//      1. 添加开始时间、结束时间
//      2. 需要修改轻应用模型
        request.setPriceStartDate(sdo.getPriceStartDate());
        request.setPriceEndDate(sdo.getPriceEndDate());

        QueryPriceDimensionConfigResponse response = pricePropertyConfigService.queryPriceDimensionConfig(request);
        PriceDimensionConfigSDO configSDO = new PriceDimensionConfigSDO();
        configSDO.setVersion(response.getVersion());
        configSDO.setId(response.getId());
        return configSDO;
    }

    @Override
    public PriceDimensionConfigSDO loadById(Long id) {
        LoadRequest request = new LoadRequest();
        request.setId(""+id);
        LoadResponse load = pricePropertyConfigService.load(request);
        return load.getResult();
    }


    /**
     * 动态列的获取方法
     * @param dimensionDesc
     * @param dimensionRule
     * @return
     */
    private Map<String,String> detailColumn(String dimensionDesc, String dimensionRule) {

        Map<String, String> dimensionMap = Maps.newHashMap();
        if (StringUtils.isBlank(dimensionDesc) || StringUtils.isBlank(dimensionRule)) {
            return dimensionMap;
        }
        String[] dimensionDescArr = dimensionDesc.split("\\+");
        String[] dimensionRuleArr = dimensionRule.split(",");

        List<ExtraShowColumn> extraShowColumns = Lists.newArrayList();

        if (dimensionDescArr.length != dimensionRuleArr.length) {
            new RuntimeException("请检查维度配置表数据是否正确" + dimensionDesc + "\n" + dimensionRule);
        }

        for (int i = 0; i < dimensionDescArr.length; i++) {
            ExtraShowColumn extraShowColumn = new ExtraShowColumn();

            extraShowColumn.setLabel(dimensionDescArr[i]);
            extraShowColumn.setKey("features." + detailCode(dimensionRuleArr[i]));


            extraShowColumns.add(extraShowColumn);
        }
        dimensionMap.put("extraShowColumns", JSONObject.toJSONString(extraShowColumns));

        return dimensionMap;
    }

    /**
     * 处理维度属性的字段编码
     * @param dimensionRule
     * @return
     */
    private String detailCode(String dimensionRule) {
        if (StringUtils.isBlank(dimensionRule)) {
            return null;
        }

        String[] dimensionRuleArr = dimensionRule.split("\\+");
        if (dimensionRuleArr.length < 2) {
            new RuntimeException("请检查维度属性配置" + dimensionRule);
        }

        return toHump(dimensionRuleArr[1]);

    }

    /**
     * 下划线转为驼峰
     * @param str
     * @return
     */
    public String toHump(String str){
        //        str = str.toLowerCase();
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 返回维度属性和值的对应关系
     * @param columnDataGroup
     * @param dimensionPropertiesGroup
     * @return
     */
    private Map<String, String> detailColumnDate(Map<String, String> columnDataGroup, String dimensionPropertiesGroup) {

        String[] columnDataSplit = dimensionPropertiesGroup.split(",");
        if (columnDataSplit.length < 1) {
            return new HashMap();
        }

        for (String columnData : columnDataSplit) {
            int index = columnData.lastIndexOf('_');
            String key = columnData.substring(0, index);
            if (index < columnData.length() - 1) {
                String value = columnData.substring(index + 1);
                columnDataGroup.put(key, value);
            }
        }
        return columnDataGroup;
    }


    /**
     * //获取维度规则属性和值list的对应关系
     * @param dimensionPropertyGroup
     * @return
     */
    private Map<String, List<String>> obtainDimensionPropertyAndDataMap(List<String> dimensionPropertyGroup) {
        Map<String, List<String>> propertyCodeMap = new HashMap<>();

        //获取维度属性组数据的所有属性
        Map propertyGroupMap = detailColumnDate(new HashMap<>(), dimensionPropertyGroup.get(0));
        List<String> propertyList = Lists.newArrayList(propertyGroupMap.keySet());

        //获取所有的数据
        List<Map<String, String>> propertyGroupList = Lists.newArrayList();
        for (String data : dimensionPropertyGroup) {
            Map<String, String> dataMap = Maps.newHashMap();
            propertyGroupList.add(detailColumnDate(dataMap, data));
        }

        //获取属性和值list的对应关系
        for (String property : propertyList) {
            Set<String> codeSet = Sets.newHashSet();
            for (Map<String, String> dataMap : propertyGroupList) {
                codeSet.add(dataMap.get(property));
            }
            propertyCodeMap.put(property, Lists.newArrayList(codeSet));
        }
        return propertyCodeMap;
    }

    /**
     * 获取属性名称1:(编码:描述)N的对应关系
     * @param dimensionPropertyCodeAndValueMap
     * @return
     */
    private Map<String, Map<String, String>> obtainDimensionPropertyMap(Map<String, List<String>> dimensionPropertyCodeAndValueMap) {
        Map<String, Map<String, String>> map = Maps.newHashMap();

        //获取维度属性
        Set<String> dimensionGroupColumn = dimensionPropertyCodeAndValueMap.keySet();
        dimensionGroupColumn.forEach(item->{
            PriceProcess activityProcess = manager.getPropertyProcess(item);
            map.put(item,new HashMap<>());
            if(Objects.nonNull(activityProcess)){
                map.put(item,manager.getPropertyProcess(item).obtainCodeAndDescMap(dimensionPropertyCodeAndValueMap.get(item),false));
            }
        });

        return map;
    }


    @Override
    public List<PriceDimensionSDO> queryPriceDimensionList(List<String> dimensionIds) {
        QueryDimensionListByDimensionIdListRequest dimensionIdListRequest
                = new QueryDimensionListByDimensionIdListRequest();
        dimensionIdListRequest.setDimensionIdList(dimensionIds);
        dimensionIdListRequest.setStart(0);
        dimensionIdListRequest.setLimit(100);
        QueryDimensionListByDimensionIdListResponse dimensionIdListResponse
                = priceDimensionService.queryDimensionListByDimensionIdList(dimensionIdListRequest);

        return JSONObject.parseArray(JSONObject.toJSONString(dimensionIdListResponse.getResult()), PriceDimensionSDO.class);

    }

    @Override
    @RepositoryInvoker
    public Result<List<RegularPriceResponse>> loadRegularPriceList(RegularPriceRequest regularPriceRequest) {
        Result<List<RegularPriceResponse>> result = Result.success(new ArrayList<>());

        //加权限控制
        List<String> organizationIds = Lists.newArrayList();
        //获取销售组织外部编码
        List<String> organizationOutCodes = Lists.newArrayList();
        GetLoginEmployOrganizationPermissionsPriceRequest permissionsPriceRequest = new GetLoginEmployOrganizationPermissionsPriceRequest();
        permissionsPriceRequest.setType(104);
        Result<List<OrganizationSDO>> loginEmployeeSaleOrganization = otsPlatformEnhanceService.getLoginEmployOrganizationPermissionsPrice(permissionsPriceRequest);
        log.info("当前登录用户的销售组织信息 = {}", JSONObject.toJSONString(loginEmployeeSaleOrganization));
        if (Objects.nonNull(loginEmployeeSaleOrganization) && CollectionUtils.isNotEmpty(loginEmployeeSaleOrganization.getResult())) {
            List<com.epoch.app.otsplatformenhance.sdo.OrganizationSDO> organizationSDOList = loginEmployeeSaleOrganization.getResult();
            if (CollectionUtils.isNotEmpty(organizationSDOList)) {
                organizationIds = organizationSDOList.stream().filter(e -> StringUtils.isNotBlank(e.getId())).distinct().map(e -> e.getId()).collect(Collectors.toList());
                Map<String, String> salesOrganizationMap = propertyProcessManager.getPropertyProcess(DimensionPropertyEnum.ORG_SALES_ORGANIZATION_CODE.getKey())
                        .obtainInnerCodeAndOuterCodeMap(organizationIds, true);
                organizationIds.forEach(e -> organizationOutCodes.add(salesOrganizationMap.get(e)));
            }
        }

        if (CollectionUtils.isEmpty(organizationOutCodes)) {
            log.error("未查询到当前登录用户的销售组织信息");
            return result;
        }

        //获取业务渠道外部编码
        List<String> channelOutCodes = Lists.newArrayList();
        GetOrgChannelRelationByOrgId2Request channelRelationByOrgId2Request = new GetOrgChannelRelationByOrgId2Request();
        channelRelationByOrgId2Request.setIds(organizationIds);
        channelRelationByOrgId2Request.setStatus(1);
        Result<List<OrganizationChannelRelationSDO>> orgChannelRelationResult = otsPlatformEnhanceService.getOrgChannelRelationByOrgId2(channelRelationByOrgId2Request);
        log.info("当前登录用户的业务渠道信息 = {}", JSONObject.toJSONString(orgChannelRelationResult));
        if (Objects.nonNull(orgChannelRelationResult) && CollectionUtils.isNotEmpty(orgChannelRelationResult.getResult())) {
            List<OrganizationChannelRelationSDO> orgChannelRelations = orgChannelRelationResult.getResult();
            channelOutCodes = orgChannelRelations.stream().filter(e -> StringUtils.isNotBlank(e.getOutCode()))
                    .map(OrganizationChannelRelationSDO::getOutCode).distinct().collect(Collectors.toList());
        }

        if (CollectionUtils.isEmpty(channelOutCodes)) {
            log.error("未查询到当前用户的渠道信息");
            return result;
        }

        String saleOrganizationCode = regularPriceRequest.getSaleOrganizationCode();
        if (StringUtils.isNotBlank(saleOrganizationCode) && !organizationOutCodes.contains(saleOrganizationCode)) {
            return result;
        }

        String channelCode = regularPriceRequest.getChannelCode();
        if (StringUtils.isNotBlank(channelCode) && !channelOutCodes.contains(channelCode)) {
            return result;
        }

        QueryListRequest queryListRequest = new QueryListRequest();
        queryListRequest.setItemCode(regularPriceRequest.getItemCode());
        queryListRequest.setItemName(regularPriceRequest.getItemName());
        queryListRequest.setSaleOrganizationCode(StringUtils.isNotBlank(saleOrganizationCode) ? Lists.newArrayList(saleOrganizationCode) : organizationOutCodes);
        queryListRequest.setChannelCode(StringUtils.isNotBlank(channelCode) ? Lists.newArrayList(channelCode) : channelOutCodes);
        queryListRequest.setCustomerSendCode(regularPriceRequest.getCustomerSendCode());
        queryListRequest.setCustomerSendName(regularPriceRequest.getCustomerSendName());
        queryListRequest.setCustomerSaleCode(regularPriceRequest.getCustomerSaleCode());
        queryListRequest.setCustomerSaleName(regularPriceRequest.getCustomerSaleName());
        queryListRequest.setPriceType(regularPriceRequest.getPriceType());
        queryListRequest.setStatus(regularPriceRequest.getStatus());
        queryListRequest.setStart(regularPriceRequest.getStart());
        queryListRequest.setLimit(regularPriceRequest.getLimit());
        Result<List<OfsPricePropertyConfigIndex>> listResult = ofsPricePropertyConfigIndexService.queryList(queryListRequest);

        if (Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())) {
            return result;
        }

        List<RegularPriceResponse> trans = listResult.getResult().stream().map(e -> {
            RegularPriceResponse regularPriceResponse = new RegularPriceResponse();
            regularPriceResponse.setSalesOrganizationDesc(e.getConfigOrgSalesOrganizationCode());
            regularPriceResponse.setChannelDesc(e.getConfigChannelCode());
            regularPriceResponse.setItemGroupDesc(e.getConfigScItemGroupCode());
            regularPriceResponse.setCustomerSendCode(e.getConfigCustomerSendAddressCodeFlag());
            regularPriceResponse.setCustomerSendDesc(e.getConfigCustomerSendAddressCode());
            regularPriceResponse.setCustomerSaleCode(e.getConfigCustomerSaleAddressCodeFlag());
            regularPriceResponse.setCustomerSaleDesc(e.getConfigCustomerSaleAddressCode());
            regularPriceResponse.setCustomerGroupDesc(e.getConfigCustomerGroup());
            regularPriceResponse.setSalesUnitDesc(e.getConfigSalesUnitCode());
            regularPriceResponse.setItemCode(e.getConfigItemId());
            regularPriceResponse.setItemName(e.getConfigMaterialCode());
            regularPriceResponse.setPriceDimension(e.getDimensionDimensionId());
            regularPriceResponse.setPriceDimensionRule(e.getDimensionDimensionDesc());
            Long recordMoneyAmount = e.getRecordMoneyAmount();
            if (Objects.nonNull(recordMoneyAmount)) {
                BigDecimal multiply = new BigDecimal(recordMoneyAmount).divide(new BigDecimal(100L));
                regularPriceResponse.setPriceAmount(multiply.setScale(2, RoundingMode.HALF_DOWN).stripTrailingZeros().toPlainString());
            }
            return regularPriceResponse;
        }).collect(Collectors.toList());

        result.setResult(trans);
        result.setTotal(listResult.getTotal());

        return result;
    }
}
